package com.example.lucky.draw.server.service.impl;

import com.example.lucky.draw.server.common.enums.DrawEnum;
import com.example.lucky.draw.server.common.enums.ErrorEnum;
import com.example.lucky.draw.server.common.handler.DrawException;
import com.example.lucky.draw.server.protocol.po.*;
import com.example.lucky.draw.server.protocol.query.ActivityQuery;
import com.example.lucky.draw.server.repository.*;
import com.example.lucky.draw.server.service.IActivityService;
import com.example.lucky.draw.server.service.IPrizeService;
import com.fasterxml.jackson.databind.util.JSONPObject;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ActivityServiceImpl implements IActivityService {

    @Autowired
    private ActivityRepository activityRepository;

    private List<Activity> activities;

    @Autowired
    private ActivityRuleRepository activityRuleRepository;

    @Autowired
    private RuleRepository ruleRepository;

    @Autowired
    private ActivityResultRepository activityResultRepository;

    @Autowired
    private IPrizeService prizeService;

    @Autowired
    private PrizeRepository prizeRepository;

    @Override
    public List<Activity> findAll(ActivityQuery activityQuery) {
        if (activities == null){
            activities = activityRepository.findAll();
        }
        String name = activityQuery.getName();
        Integer status = activityQuery.getStatus();
        return activities.stream()
                .filter(activity -> name == null || name =="" || name.equals(activity.getName()))
                .filter(activity -> status == null || status.equals(activity.getStatus()))
                .collect(Collectors.toList());
    }

    @Override
    public List<Activity> findAll() {
        Integer status=Integer.valueOf(DrawEnum.ENABLE.getCode());
        List<Activity> activityList= activityRepository.findByStatusEquals(status);
        return activityList;
    }

    @Override
    public void save(Activity activity) {
        LocalDateTime now = LocalDateTime.now();
        activity.setCreateTime(now);
        activity.setUpdateTime(now);
        activity.setStatus(0);//待审核
        activityRepository.save(activity);
        activities = null;
    }

    @Override
    public Activity findActivityById(Long id) {
        Optional<Activity> activityOptional = activityRepository.findById(id);
        Activity activity = activityOptional.orElse(null);
        return activity;
    }

    @Override
    public Prize trigger(Long id) throws JSONException {
        //1.获取活动规则，用于检测用户权限
        List<ActivityRule> activityRules = activityRuleRepository.findByActivityId(id);
        List<Long> ruleIds = activityRules.stream().map(ActivityRule::getRuleId).collect(Collectors.toList());
        List<Rule> ruleList = ruleRepository.findAllById(ruleIds);
        boolean value=false;
        for (Rule rule : ruleList) {
            //如果type = 1，则当前规则用于限制用户抽奖次数
            if (rule.getType()==1){
                //获取当前活动所配置的抽奖次数
                JSONObject jsonObject = new JSONObject(rule.getContent());
                //获取count的属性
                Integer count = jsonObject.getInt("count");
                //获取用户已经参与的次数
                Long userId=getUserId();
                Integer result = activityResultRepository.countActivityResultByActivityIdAndUserId(id, userId);
                if (result>=count){
                    throw new DrawException(DrawEnum.TIMES_EXHAUSTED);
                }
            }else {
                //检测概率是否降低
                JSONObject jsonObject = new JSONObject(rule.getContent());
                value = jsonObject.getBoolean("value");
            }
        }
        //2.获取活动奖品，用于计算中奖结果
        List<Prize> prizes = prizeService.findAllByActivityId(id);
        //3.返回中奖奖品
        // 分配抽奖概率
        Map<Prize, Double> prizeProbabilityMap = new HashMap();
        //逆价值-> 1/奖品价值
        double totalInverseValue = prizes.stream().mapToDouble(prize -> 1.0 / prize.getValue()).sum();

        // 如果需要降低概率，则所有概率值乘以一个小于1的因子
        double decreaseFactor = value ? 0.5 : 1.0;
        for (Prize prize : prizes) {
            double individualProbability = (1.0 / prize.getValue()) / totalInverseValue;
            prizeProbabilityMap.put(prize, individualProbability * decreaseFactor);
        }
        // 执行抽奖
        double randomValue = new Random().nextDouble();
        double cumulativeProbability = 0.0;
        for (Map.Entry<Prize, Double> entry : prizeProbabilityMap.entrySet()) {
            Prize prize = entry.getKey();
            Double probability = entry.getValue();

            cumulativeProbability += probability;
            if (randomValue <= cumulativeProbability) {
                prize.setStock(prize.getStock()-1);
                prizeRepository.save(prize);//更新奖品库存
                saveActivityResult(id,prize.getId());//记录中奖信息
                return prize; // 返回中奖的奖品对象
            }
        }
        // 如果没有抽中任何奖品
        Prize prize = new Prize();
        prize.setId(999999999L);
        prize.setName("谢谢参与");
        prize.setImg("https://img.tukuppt.com/png_preview/00/44/90/VDa2b4drT2.jpg%21/fw/780");
        saveActivityResult(id,prize.getId());
        return prize; // 根据业务需求返回默认奖品或处理为未中奖
    }

    private void saveActivityResult(Long activityId, Long prizeId) {
        ActivityResult activityResult = new ActivityResult();
        activityResult.setActivityId(activityId);
        activityResult.setPrizeId(prizeId);
        activityResult.setUserId(getUserId());
        activityResult.setWinTime(LocalDateTime.now());
        //未发放
        activityResult.setStatus(0);
        activityResultRepository.save(activityResult);
    }

    private Long getUserId() {
        return 99999L;
    }
}
